package com.wankuma.hcm.midlet.metwit;

import METwit;

import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import java.util.Vector;

import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;

import org.kxml2.io.KXmlParser;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import net.siisise.io.BASE64;

/**
 * ﾀｲﾑﾗｲﾝの取得処理を行うThreadです.
 * 
 * @author Harada Hirotsugu
 */
public class TimeLineOperation implements Runnable {
	
	private Callback tlcListener;
	private MainScreen mainScreen;
	private int timeLineId;

	public TimeLineOperation(int tlid, Callback cl) {
		this.timeLineId = tlid;
		this.tlcListener = cl;
		this.mainScreen = METwit.getMainScreen();
	}

	public void run() {
		
		mainScreen.setTickerString(StringRes.GETTING_TIMELINE);

		Config config = Config.getInstance();

		HttpConnection c = null;
		InputStream is = null;
		XmlPullParser xr = null;

		Calendar lastModified = Status.getLastModified(timeLineId);
		String url = getApiUrl(timeLineId);

		if (lastModified == null
				|| ((new Date().getTime() - lastModified.getTime().getTime()) > 120000)) {
			try {
				BASE64 b64 = new BASE64();

				c = (HttpConnection) Connector.open(url);
				c.setRequestMethod(HttpConnection.GET);
				c.setRequestProperty("Authorization", "Basic "
						+ b64.encode((config.getUser() + ":" + config
								.getPassword()).getBytes()));
				if (lastModified != null) {
					String strLastModified = CalenderUtil
							.calenderToString(lastModified);
					c.setRequestProperty("If-Modified-Since", strLastModified);
				}
				c.setRequestProperty("X-Twitter-Client", "METwit");

				int code = c.getResponseCode();
				if (code == 200) {
					lastModified = Calendar.getInstance(TimeZone
							.getTimeZone("UTC"));
					Status.setLastModified(timeLineId, lastModified);

					is = c.openInputStream();
					xr = new KXmlParser();
					xr.setInput(is, "UTF-8");

					int type;
					Vector vctStatuses = new Vector();
					Status s = null;
					boolean bUserMode = false;
					while ((type = xr.next()) != XmlPullParser.END_DOCUMENT) {
						if (type == XmlPullParser.START_TAG) {
							String tag = xr.getName();
							if (tag.equals("status")) {
								s = new Status();
							} else if (tag.equals("created_at")) {
								String str = xr.nextText();
								s.setCreateAt(str);
							} else if (tag.equals("id")) {
								String str = xr.nextText();
								if (!bUserMode) {
									s.setId(Long.parseLong(str));
								} else {
									s.setUserId(Long.parseLong(str));
								}
							} else if (tag.equals("text")) {
								String str = xr.nextText();
								str = StringRes.replaceString(str, "&lt;", "<");
								str = StringRes.replaceString(str, "&gt;", ">");
								str = StringRes
										.replaceString(str, "&amp;", "&");
								str = StringRes.replaceString(str, "&quot;",
										"\"");
								str = StringRes.replaceString(str, "&apos;",
										"'");
								s.setText(str);
							} else if (tag.equals("source")) {
								String str = xr.nextText();
								StringBuffer sb = new StringBuffer();
								boolean bIgnore = false;
								for (int i = 0; i < str.length(); i++) {
									char ch = str.charAt(i);
									if (ch == '<')
										bIgnore = true;
									if (ch == '>') {
										bIgnore = false;
										continue;
									}
									if (!bIgnore)
										sb.append(ch);
								}
								str = sb.toString();
								s.setSource(str);
							} else if (tag.equals("user")) {
								bUserMode = true;
							} else if (tag.equals("name")) {
								String str = xr.nextText();
								s.setName(str);
							} else if (tag.equals("screen_name")) {
								String str = xr.nextText();
								s.setScreenName(str);
							}
						} else if (type == XmlPullParser.END_TAG) {
							String tag = xr.getName();
							if (tag.equals("status")) {
								vctStatuses.addElement(s);
							} else if (tag.equals("user")) {
								bUserMode = false;
							}
						}
					}

					Vector gtl = Status.getTimeLine(timeLineId);
					Status ls = null;
					if (gtl.size() > 0)
						ls = (Status) gtl.elementAt(0);
					int cnt = 0;
					for (int i = (vctStatuses.size() - 1); i >= 0; i--) {
						Status cs = (Status) vctStatuses.elementAt(i);
						if (ls != null && (cs.getId() <= ls.getId()))
							continue;
						gtl.insertElementAt(cs, 0);
						cnt++;
					}

					// getTimeLineCapacity件に制限.効率悪いかも.
					int cap = config.getTimeLineCapacity();
					while (gtl.size() > cap)
						gtl.removeElementAt(cap);

					// 表示実行
					StatusDetailScreen.getInstance().addIndex(cnt);
					tlcListener.gotTimeLineAction(timeLineId, cnt);

					// ｶﾞﾍﾞｰｼﾞｺﾚｸﾀ強制実行してみる.
					System.gc();

					mainScreen.setTickerString(StringRes.HTTP_200 + " "
							+ Integer.toString(cnt) + StringRes.GET_SUCCEED);
				} else if (code == 304) {
					mainScreen.setTickerString(StringRes.HTTP_304
							+ StringRes.NOT_MODIFIED);
				} else if (code == 400) {
					mainScreen.setTickerString(StringRes.HTTP_400
							+ StringRes.API_CONTROLED);
				} else if (code == 401) {
					mainScreen.setTickerString(StringRes.HTTP_401
							+ StringRes.NOT_AUTHORIZED);

				} else {
					mainScreen.setTickerString("HTTP"
							+ new Integer(code).toString() + "."
							+ StringRes.SERVER_IS_DOWN);
				}
				mainScreen.setRemoveTickerTimer(10000);
				// METwit.getDisplay().setCurrent(mainScreen);
			//} catch (Exception ex) {
			//	Alerter.alert(ex.toString());
			} finally {
				try {
					if (is != null)
						is.close();
					if (c != null)
						c.close();
				} catch (Exception ex) {
					Alerter.alert(ex.toString());
				}
			}
		} else {
			mainScreen.setTickerString(StringRes.FAILBY_SELF_CONTROL);
			mainScreen.setRemoveTickerTimer(10000);
			// METwit.getDisplay().setCurrent(mainScreen);
			long remained = new Date().getTime()
					- lastModified.getTime().getTime();
			remained = 120 - remained / 1000;
			Alerter.alert(StringRes.MSG_SELF_CONTROL,
					StringRes.TITLE_SELF_CONTROL + "(あと"
							+ Long.toString(remained) + "秒)");
		}
	}

	private static String getApiUrl(int tlid) {
		switch (tlid) {
		case Status.FRIENDS:
			return "http://twitter.com/statuses/friends_timeline.xml";
		case Status.REPLIES:
			return "http://twitter.com/statuses/replies.xml";
		case Status.ARCHIVE:
			return "http://twitter.com/statuses/user_timeline.xml";
		case Status.PUBLIC:
			return "http://twitter.com/statuses/public_timeline.xml";
		default:
			return null;
		}
	}

	public interface Callback {
		public void gotTimeLineAction(int tlid, int cnt);
	}
}
